﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.Feeds.Interop;
using Bonobo.Reader.Feeds.MenuCommands;
using Bonobo.Reader.Feeds.UI;

namespace Bonobo.Reader.Feeds
{
    public class FeedsItemProvider : BonoboItemProvider
    {
        private List<BonoboMenuCommand> _menuCommands;
        private FeedItemResourceDictionary _itemResourceDictionary;

        public FeedsItemProvider()
        {
            _menuCommands = new List<BonoboMenuCommand>() { new AddNewFeedCommand() };
            _itemResourceDictionary = new FeedItemResourceDictionary();
        }


        public override IEnumerable<BonoboMenuCommand> MenuCommands
        {
            get { return _menuCommands; }
        }

        public override System.Windows.DataTemplate ItemDataTemplate
        {
            get { return _itemResourceDictionary.DataTemplate; }
        }

        public override Type ItemType
        {
            get { return typeof(FeedItem); }
        }

        public override ObservableCollection<BonoboItem> GetItems(BonoboItemFilter filter)
        {
            var items = from folder in GetAllFolders(filter.Tags)
                        from feed in ((IFeedsEnum)(folder.Feeds)).Cast<IFeed>()
                        from item in ((IFeedsEnum)(feed.Items)).Cast<IFeedItem>()
                        where (!filter.OnlyUnread || item.IsRead == false)
                        orderby item.PubDate descending
                        select CreateItem(item);

            return new ObservableCollection<BonoboItem>(GetRangedValues(items.ToArray(), filter.StartIndex, filter.ItemCount));
        }

        private IEnumerable<BonoboItem> GetRangedValues(BonoboItem[] items, int start, int count)
        {
            var list = new List<BonoboItem>();
            for (int i = start; i < start + count && i < items.Length; i++)
            {
                list.Add(items[i]);
            }
            return list;
        }

        private static BonoboItem CreateItem(IFeedItem item)
        {
            return new FeedItem(item);
        }

        private static IEnumerable<IFeedFolder> GetAllFolders(IEnumerable<String> tags)
        {
            var manager = new FeedsManager();

            try
            {
                return GetAllFolders(manager.RootFolder, tags);
            }
            finally
            {
                Marshal.ReleaseComObject(manager);
            }
        }

        private static List<IFeedFolder> GetAllFolders(Object root, IEnumerable<String> tags)
        {
            var list = new List<IFeedFolder>();
            if (tags == null || tags.Count() == 0)
            {
                GetAllFolders((IFeedFolder)(root), list);
            }
            else
            {
                GetAllFolders((IFeedFolder)(root), list, tags);
            }
            return list;
        }

        private static void GetAllFolders(IFeedFolder folder, List<IFeedFolder> list, IEnumerable<String> tags)
        {
            if (tags.Contains(folder.Name))
            {
                list.Add(folder);
            }

            foreach (var subfolder in ((IFeedsEnum)(folder.Subfolders)).Cast<IFeedFolder>())
            {
                GetAllFolders(subfolder, list, tags);
            }
        }

        private static void GetAllFolders(IFeedFolder folder, List<IFeedFolder> list)
        {
            list.Add(folder);

            foreach (var subfolder in ((IFeedsEnum)(folder.Subfolders)).Cast<IFeedFolder>())
            {
                GetAllFolders(subfolder, list);
            }
        }
    }
}
